from django.core import serializers
from rest_framework.decorators import action
from rest_framework.utils import json
from django.utils import timezone
from datetime import datetime

from dvadmin.system.models import Activity, Users, Goods, ActivityRecord, ActivityParameter
from dvadmin.utils.json_response import DetailResponse, SuccessResponse, ErrorResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet


class ActivitySerializer(CustomModelSerializer):
    """
    Activity management interface - serializer
    """

    class Meta:
        model = Activity
        fields = "__all__"
        read_only_fields = ["id"]


class ActivityRecordSerializer(CustomModelSerializer):
    """
    Activity record management interface - serializer
    """

    class Meta:
        model = ActivityRecord
        fields = "__all__"
        read_only_fields = ["id"]


class ActivityCreateUpdateSerializer(CustomModelSerializer):
    """
    Activity management interface - serializer for creating/updating
    """

    def validate(self, attrs: dict):
        return super().validate(attrs)

    class Meta:
        model = Activity
        fields = '__all__'


class ActivityViewSet(CustomModelViewSet):
    """
    Activity management interface
    list: query
    create: add
    update: modify
    retrieve: single instance
    destroy: delete
    """
    queryset = Activity.objects.all()
    serializer_class = ActivitySerializer

    @action(methods=['GET'], detail=True)
    def role_get_menu(self, request):
        app_user_queryset = Activity.objects.filter(users__id=request.user.id).values_list('data_range', flat=True)
        return DetailResponse(data=app_user_queryset)

    @action(methods=['GET'], detail=False)
    def activity_hot(self, request):
        """Get hot activities"""
        try:
            # Get activity list
            queryset = Activity.objects.all()
            result_list = list(queryset.values())
            
            # Get all needed user IDs
            user_ids = [item.get('user_id') for item in result_list if item.get('user_id') is not None]

            # Get user information
            users_dict = {}
            if user_ids:
                users_queryset = Users.objects.filter(id__in=user_ids)
                for user in users_queryset:
                    users_dict[user.id] = {
                        'id': user.id,
                        'name': user.name,
                        'phone': user.mobile,  # Use the user's phone number
                        'shop_address': user.shop_address,  # Use the user's shop address
                    }

            # Get goods information
            goods_dict = {}
            if user_ids:
                goods_queryset = Goods.objects.filter(shop_id__in=user_ids)
                for goods in goods_queryset:
                    if goods.shop_id not in goods_dict:
                        goods_dict[goods.shop_id] = []
                    goods_dict[goods.shop_id].append({
                        'id': goods.id,
                        'name': goods.goods_name,
                        'price': goods.goods_price,
                        'image': goods.goods_image
                    })

            # Assemble the return data
            for item in result_list:
                user_id = item.get('user_id')
                if user_id and user_id in users_dict:
                    user_info = users_dict[user_id]
                    item['phone'] = user_info['phone']
                    item['shop_address'] = user_info['shop_address']
                else:
                    item['phone'] = None
                    item['shop_address'] = None

                # Get activity status
                item['active_status'] = self.get_activity_status(item)

                # Add goods information
                if user_id and user_id in goods_dict:
                    item['goods'] = goods_dict[user_id]
                else:
                    item['goods'] = []

            return SuccessResponse(data=result_list, total=len(result_list), msg="Successfully retrieved")

        except Exception as e:
            return ErrorResponse(msg=f"Failed to get hot activities: {str(e)}")

    def get_activity_status(self, activity):
        """Calculate activity status based on time and other factors"""
        try:
            current_time = timezone.now()
            start_time = activity.get('create_start_time')
            end_time = activity.get('create_end_time')
            
            if not start_time or not end_time:
                return 0  # Not started
            
            if isinstance(start_time, str):
                start_time = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
            if isinstance(end_time, str):
                end_time = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
            
            if current_time < start_time:
                return 0  # Not started
            elif current_time > end_time:
                return 2  # Finished
            else:
                return 1  # In progress
            
        except Exception:
            return 0  # Default not started if there's an error

    @action(methods=['GET'], detail=False)
    def activity_nearest(self, request):
        """Get nearest activities"""
        try:
            app_user_queryset = Activity.objects.all()
            result_list = list(app_user_queryset.values())
            
            # 获取所有需要的用户ID
            user_ids = [item.get('user_id') for item in result_list if item.get('user_id') is not None]

            # 获取用户当前位置（从请求参数中获取）
            user_lat = request.query_params.get('latitude')
            user_lng = request.query_params.get('longitude')

            # 构建用户字典
            users_queryset = Users.objects.filter(id__in=user_ids)
            users_dict = {user.id: user for user in users_queryset}
            
            for item in result_list:
                # 循环给Users查询具体id并把users放入这个item中
                if item.get('user_id') is not None:
                    user = users_dict.get(item.get('user_id'))
                    if user:
                        item['users'] = serializers.serialize('json', [user])
                    else:
                        item['users'] = None
                else:
                    item['users'] = None
                    
                # 计算评分和距离
                item['score'] = self.calculate_activity_score(item.get('id', 0))  # 使用活动ID
                
                # 如果提供了用户位置，计算距离
                if user_lat and user_lng:
                    shop_user = users_dict.get(item.get('user_id'))
                    if shop_user:
                        item['distance'] = self.calculate_distance(
                            user_lat, 
                            user_lng, 
                            shop_user.latitude, 
                            shop_user.longitude
                        )
                    else:
                        item['distance'] = None
                else:
                    item['distance'] = None

            # 获取商品信息
            goods_queryset = Goods.objects.filter(shop_id__in=user_ids)
            goods_dict = {user.id: user for user in goods_queryset}
            
            for item in result_list:
                if item.get('user_id') is not None:
                    user = goods_dict.get(item.get('user_id'))
                    if user:
                        item['goods'] = serializers.serialize('json', [user])
                    else:
                        item['goods'] = None
                else:
                    item['goods'] = None
                    
            return SuccessResponse(data=result_list, total=len(result_list), msg="Successfully retrieved")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to get nearest activities: {str(e)}")

    @action(methods=['GET'], detail=False)
    def activity_participate(self, request):
        app_user_queryset = Activity.objects.filter(activity_type=1).all()
        result_list = list(app_user_queryset.values())
        # 获取所有需要的用户ID
        user_ids = [item.get('user_id') for item in result_list if item.get('user_id') is not None]

        # 构建用户字典
        users_queryset = Users.objects.filter(id__in=user_ids)
        users_dict = {user.id: user for user in users_queryset}
        for item in result_list:
            # 循环给Users查询具体id并把users放入这个item中
            if item.get('user_id') is not None:
                user = users_dict.get(item.get('user_id'))
                if user:
                    item['users'] = serializers.serialize('json', [user])
                else:
                    item['users'] = None
            else:
                item['users'] = None
            if item.get('user_id') is not None:
                user = users_dict.get(item.get('user_id'))
                if user:
                    item['phone'] = user.mobile
                    item['shop_address'] = user.shop_address
                    item['active_status'] = self.get_activity_status(item)

        goods_queryset = Goods.objects.filter(shop_id__in=user_ids)

        goods_dict = {user.id: user for user in goods_queryset}
        for item in result_list:
            if item.get('user_id') is not None:
                user = goods_dict.get(item.get('user_id'))
                if user:
                    item['goods'] = serializers.serialize('json', [user])
                else:
                    item['goods'] = None
            else:
                item['goods'] = None
        return SuccessResponse(data=result_list, total=len(result_list), msg="Successfully retrieved")

    """
    Lottery activity data query
    """

    @action(methods=['GET'], detail=False)
    def activity_lottery(self, request):
        app_user_queryset = Activity.objects.filter(activity_type=1).all()
        result_list = list(app_user_queryset.values())
        # 获取所有需要的用户ID
        user_ids = [item.get('user_id') for item in result_list if item.get('user_id') is not None]

        # 构建用户字典
        users_queryset = Users.objects.filter(id__in=user_ids)
        users_dict = {user.id: user for user in users_queryset}
        for item in result_list:
            # 循环给Users查询具体id并把users放入这个item中
            if item.get('user_id') is not None:
                user = users_dict.get(item.get('user_id'))
                if user:
                    item['users'] = serializers.serialize('json', [user])
                else:
                    item['users'] = None
            else:
                item['users'] = None

        goods_queryset = Goods.objects.filter(shop_id__in=user_ids)

        goods_dict = {user.id: user for user in goods_queryset}
        for item in result_list:
            if item.get('user_id') is not None:
                user = goods_dict.get(item.get('user_id'))
                if user:
                    item['goods'] = serializers.serialize('json', [user])
                else:
                    item['goods'] = None
            else:
                item['goods'] = None

        return SuccessResponse(data=result_list, total=len(result_list), msg="Successfully retrieved")

    @action(methods=['POST'], detail=True)
    def participate(self, request, pk=None):
        """
        Participate in lottery activity - user selects an option
        """
        try:
            activity = self.get_object()
            
            # Check activity status
            if activity.activity_status != 1:
                return ErrorResponse(msg="Activity is not in progress")
            
            # Get user's selected option (1 or 2)
            selected_option = request.data.get('selected_option')
            if selected_option not in [1, 2]:
                return ErrorResponse(msg="Invalid option selected. Please choose 1 or 2")
            
            # Check if user has already participated
            if ActivityRecord.objects.filter(
                activity_id=activity.id,
                winners_user_id=request.user.id
            ).exists():
                return ErrorResponse(msg="You have already participated in this activity")

            # Create participation record with user's selection
            ActivityRecord.objects.create(
                activity_id=activity.id,
                winners_user_id=request.user.id,
                winners_user=request.user.name,
                activity_type=activity.activity_type,
                selected_option=selected_option,  # Store user's choice
                winners_status="Pending",  # Waiting for draw
                prize_status="Not distributed"
            )

            # Update participant count
            activity.participant_count = activity.participant_count + 1 
            activity.save()

            return SuccessResponse(msg="Successfully participated in the lottery")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to participate: {str(e)}")

    @action(methods=['POST'], detail=True)
    def draw_lottery(self, request, pk=None):
        """
        Draw lottery - admin selects winning option
        """
        try:
            activity = self.get_object()
            
            # Check activity status
            if activity.activity_status != 1:
                return ErrorResponse(msg="Activity cannot be drawn at this time")
            
            # Get admin's selected winning option
            winning_option = request.data.get('winning_option')
            if winning_option not in [1, 2]:
                return ErrorResponse(msg="Invalid winning option. Please choose 1 or 2")

            # Get all participants who chose the winning option
            winners = ActivityRecord.objects.filter(
                activity_id=activity.id,
                selected_option=winning_option,
                winners_status="Pending"
            )
            
            # Update winners
            winners.update(
                winners_status="Won",
                prize_status="Pending distribution"
            )
            
            # Update non-winners
            ActivityRecord.objects.filter(
                activity_id=activity.id,
                selected_option__ne=winning_option,
                winners_status="Pending"
            ).update(winners_status="Not won")

            # Update activity status
            activity.activity_status = 2  # End activity
            activity.winning_option = winning_option  # Store winning option
            activity.save()

            # Prepare winner data
            winner_data = [{
                'user_id': winner.winners_user_id,
                'username': winner.winners_user,
                'selected_option': winner.selected_option
            } for winner in winners]

            return SuccessResponse(data={
                'winning_option': winning_option,
                'total_winners': len(winner_data),
                'winners': winner_data
            }, msg="Successfully completed lottery draw")

        except Exception as e:
            return ErrorResponse(msg=f"Failed to draw lottery: {str(e)}")

    @action(methods=['GET'], detail=True)
    def get_result(self, request, pk=None):
        """
        Get activity results
        """
        try:
            activity = self.get_object()
            
            if activity.activity_status == 1:
                return ErrorResponse(msg="Activity is still in progress")
            
            # Get all participants
            records = ActivityRecord.objects.filter(activity_id=activity.id)
            
            # Get all participant user details
            participants = [{
                'user_id': record.winners_user_id,
                'username': record.winners_user,
                'participation_time': record.create_datetime.strftime('%Y-%m-%d %H:%M:%S'),
                'user_info': {
                    'name': record.winners_user,
                    'mobile': getattr(record, 'mobile', None),
                    'email': getattr(record, 'email', None),
                    'avatar': getattr(record, 'avatar', None)
                }
            } for record in records]

            result_data = {
                'activity_status': activity.get_activity_status_display(),
                'total_participants': activity.participant_count,
                'participants': participants,  # All participants
            }

            # If it's a lottery activity, add lottery-related information
            if activity.activity_type == 2:  # Lottery activity
                lottery_data = {
                    'winning_option': activity.winning_option,
                    'winners': []  # Default to an empty list
                }
                
                # If the draw has been completed, add winning information
                if activity.activity_status == 2:  # Finished
                    winners = [{
                        'user_id': record.winners_user_id,
                        'username': record.winners_user,
                        'selected_option': record.selected_option,
                        'status': record.winners_status,
                        'prize_status': record.prize_status,
                        'participation_time': record.create_datetime.strftime('%Y-%m-%d %H:%M:%S'),
                        'user_info': {
                            'name': record.winners_user,
                            'mobile': getattr(record, 'mobile', None),
                            'email': getattr(record, 'email', None),
                            'avatar': getattr(record, 'avatar', None)
                        }
                    } for record in records if record.winners_status == "Won"]
                    lottery_data['winners'] = winners
                    
                result_data.update(lottery_data)

            return SuccessResponse(data=result_data, msg="Successfully retrieved results")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to get results: {str(e)}")

    @action(methods=['POST'], detail=True)
    def record_browse(self, request, pk=None):
        """Record user's browse action"""
        try:
            activity = self.get_object()
            user = request.user
            
            # Record user browsing
            ActivityRecord.objects.create(
                activity_id=activity.id,
                winners_user_id=user.id,
                winners_user=user.username,
                activity_type=activity.activity_type,
                winners_status="Browsed"
            )
            
            # Update user's browsing count
            user.browse_count = (user.browse_count or 0) + 1
            user.save()
            
            return SuccessResponse(msg="Browse recorded successfully")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to record browse: {str(e)}")

    def retrieve(self, request, *args, **kwargs):
        """Get activity detail"""
        try:
            instance = self.get_object()
            serializer = self.get_serializer(instance)
            result = serializer.data

            # 获取活动创建者信息
            if instance.user_id:
                user = Users.objects.filter(id=instance.user_id).first()
                if user:
                    result['creator_info'] = {
                        'id': user.id,
                        'name': user.name,
                        'phone': user.mobile,
                        'shop_address': user.shop_address,
                    }

            # 获取活动参数设置
            activity_params = ActivityParameter.objects.filter(
                activity_id=instance.id
            ).values()
            result['prize_settings'] = list(activity_params)

            # 获取活动统计信息
            participant_count = ActivityRecord.objects.filter(
                activity_id=instance.id
            ).count()

            winners_count = ActivityRecord.objects.filter(
                activity_id=instance.id,
                winners_status='Won'
            ).count()

            result['statistics'] = {
                'participant_count': participant_count,
                'winners_count': winners_count,
                'conversion_rate': round(winners_count / participant_count, 2) if participant_count > 0 else 0
            }

            # 记录浏览
            if request.user and request.user.is_authenticated:
                ActivityRecord.objects.create(
                    activity_id=instance.id,
                    winners_user_id=request.user.id,
                    winners_user=request.user.username,
                    activity_type=instance.activity_type,
                    winners_status="Browsed"
                )
                
                # Update user's browsing count
                request.user.browse_count = (request.user.browse_count or 0) + 1
                request.user.save()

            return DetailResponse(data=result, msg="Successfully retrieved activity details")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to get activity details: {str(e)}")

    def calculate_activity_score(self, activity_id):
        """Calculate activity score from ratings"""
        try:
            from dvadmin.system.models import RateReviews
            # 获取该活动的所有评分
            ratings = RateReviews.objects.filter(
                business_id=activity_id,
                business_type=1  # 1表示活动评价
            )
            if not ratings.exists():
                return 0
            # 计算平均分
            avg_score = ratings.aggregate(
                avg_score=models.Avg('reviews_starts')
            )['avg_score'] or 0
            return round(avg_score, 1)
        except Exception:
            return 0

    def calculate_distance(self, user_lat, user_lng, shop_lat, shop_lng):
        """Calculate distance between user and shop"""
        try:
            from math import sin, cos, sqrt, atan2, radians
            if not all([user_lat, user_lng, shop_lat, shop_lng]):
                return None
                
            # Convert string coordinates to float
            user_lat = float(user_lat)
            user_lng = float(user_lng)
            shop_lat = float(shop_lat)
            shop_lng = float(shop_lng)
            
            # Approximate radius of earth in km
            R = 6371.0
            
            lat1 = radians(user_lat)
            lon1 = radians(user_lng)
            lat2 = radians(shop_lat)
            lon2 = radians(shop_lng)
            
            dlon = lon2 - lon1
            dlat = lat2 - lat1
            
            a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
            c = 2 * atan2(sqrt(a), sqrt(1 - a))
            
            distance = R * c
            return round(distance, 1)  # Return distance in km
        except Exception:
            return None

    @action(methods=['GET'], detail=False)
    def activity_list(self, request):
        """Get activity list with filter"""
        try:
            # 获取活动类型筛选参数
            activity_type = request.query_params.get('activity_type')
            
            # 构建查询条件
            queryset = Activity.objects.all()
            
            # 如果指定了活动类型，则进行过滤
            if activity_type:
                try:
                    activity_type = int(activity_type)
                    if activity_type in [1, 2, 3]:  # 1:推广活动, 2:抽奖活动, 3:捐赠活动
                        queryset = queryset.filter(activity_type=activity_type)
                except (TypeError, ValueError):
                    return ErrorResponse(msg="Invalid activity type")

            # 获取活动列表
            result_list = list(queryset.values(
                'id',
                'activity_name',
                'activity_name_zn',
                'activity_detail',
                'activity_detail_zn',
                'activity_img',
                'activity_tag',
                'activity_type',
                'activity_status',
                'create_start_time',
                'create_end_time',
                'activity_rules',
                'activity_manner',
                'user_id'
            ))

            # 获取所有需要的用户ID
            user_ids = [item.get('user_id') for item in result_list if item.get('user_id') is not None]

            # 获取用户信息
            users_dict = {}
            if user_ids:
                users_queryset = Users.objects.filter(id__in=user_ids)
                for user in users_queryset:
                    users_dict[user.id] = {
                        'id': user.id,
                        'name': user.name,
                        'phone': user.mobile,
                        'shop_address': user.shop_address,
                    }

            # 组装返回数据
            for item in result_list:
                # 添加用户信息
                user_id = item.get('user_id')
                if user_id and user_id in users_dict:
                    item['user_info'] = users_dict[user_id]
                else:
                    item['user_info'] = None

                # 添加活动状态
                item['active_status'] = self.get_activity_status(item)

                # 添加参与人数统计
                item['participant_count'] = ActivityRecord.objects.filter(
                    activity_id=item['id']
                ).count()

            return SuccessResponse(data=result_list, msg="Successfully retrieved activity list")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to get activity list: {str(e)}")


class ActivityRecordViewSet(CustomModelViewSet):
    """
    Activity record management interface
    """
    queryset = ActivityRecord.objects.all()
    serializer_class = ActivityRecordSerializer

    @action(methods=['GET'], detail=False)
    def get_enums(self, request):
        """Get enumerations for activity record form"""
        try:
            # Get all users for participant selection
            users = Users.objects.filter(is_active=True).values('id', 'username', 'name')
            
            # Get all activity awards for prize selection
            activity_awards = ActivityParameter.objects.values('id', 'activity_awards')
            
            # Get activity types
            activity_types = [
                {'value': choice[0], 'label': choice[1]} 
                for choice in ActivityRecord.ACTIVITY_TYPE_CHOICES
            ]
            
            # Get winner status options
            winner_status_options = [
                {'value': 'Pending', 'label': 'Pending'},
                {'value': 'Won', 'label': 'Won'},
                {'value': 'Not won', 'label': 'Not won'}
            ]
            
            # Get prize status options
            prize_status_options = [
                {'value': 'Not distributed', 'label': 'Not distributed'},
                {'value': 'Pending distribution', 'label': 'Pending distribution'},
                {'value': 'Distributed', 'label': 'Distributed'}
            ]

            data = {
                'users': [
                    {
                        'value': user['id'],
                        'label': f"{user['username']} ({user['name']})" if user['name'] else user['username']
                    } 
                    for user in users
                ],
                'activity_awards': [
                    {
                        'value': award['id'],
                        'label': award['activity_awards']
                    }
                    for award in activity_awards
                ],
                'activity_types': activity_types,
                'winner_status_options': winner_status_options,
                'prize_status_options': prize_status_options
            }
            
            return DetailResponse(data=data, msg="Successfully retrieved enumerations")
            
        except Exception as e:
            return ErrorResponse(msg=f"Failed to get enumerations: {str(e)}")